package com.hmkj.core.service.amount.impl;

import com.alibaba.fastjson.JSON;
import com.hmkj.common.baseMapper.GenericMapper;
import com.hmkj.common.baseMapper.GenericPo;
import com.hmkj.common.utils.BigDecimalUtils;
import com.hmkj.common.utils.DateUtils;
import com.hmkj.common.utils.OrderNoUtils;
import com.hmkj.common.utils.StringUtils;
import com.hmkj.core.api.hrpay.HRPayUtils;
import com.hmkj.core.api.lianlian.*;
import com.hmkj.core.api.lianlian.enums.PayResultEnum;
import com.hmkj.core.api.umf.UmfEndPoint;
import com.hmkj.core.api.umf.domain.ResultCode;
import com.hmkj.core.api.umf.domain.UmfCommon;
import com.hmkj.core.constant.ConfigNID;
import com.hmkj.core.constant.LockId;
import com.hmkj.core.exception.BussinessException;
import com.hmkj.core.mapper.amount.AccountLogMapper;
import com.hmkj.core.mapper.amount.AccountMapper;
import com.hmkj.core.mapper.amount.CashMapper;
import com.hmkj.core.mapper.user.UserBankMapper;
import com.hmkj.core.mapper.user.UserFreezeMapper;
import com.hmkj.core.mapper.user.UserMapper;
import com.hmkj.core.model.amount.AccountModel;
import com.hmkj.core.model.amount.CashModel;
import com.hmkj.core.po.amount.Account;
import com.hmkj.core.po.amount.AccountLog;
import com.hmkj.core.po.amount.Cash;
import com.hmkj.core.po.amount.Recharge;
import com.hmkj.core.po.user.User;
import com.hmkj.core.po.user.UserBank;
import com.hmkj.core.po.user.UserFreeze;
import com.hmkj.core.service.amount.AccountService;
import com.hmkj.core.service.amount.CashService;
import com.hmkj.core.service.cache.LockService;
import com.hmkj.core.service.cache.RedisService;
import com.hmkj.core.service.system.ConfigureService;
import com.lianlianpay.security.utils.LianLianPaySecurity;
import com.lianpay.api.util.TraderRSAUtil;
import com.umpay.api.common.ReqData;
import com.umpay.api.exception.ReqDataException;
import com.umpay.api.exception.RetDataException;
import com.umpay.api.paygate.v40.Mer2Plat_v40;
import com.umpay.api.paygate.v40.Plat2Mer_v40;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * 操作权限业务相关Service接口实现<br>
 *
 * @author donfy
 * @date 2017-08-15 08:16:12
 */
@Slf4j
@Service
@Scope("prototype")
@Transactional(rollbackFor = Exception.class)
public class CashServiceImpl implements CashService {

    @Resource
    private CashMapper cashMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private AccountMapper accountMapper;
    @Resource
    private AccountLogMapper accountLogMapper;
    @Resource
    private RedisService redisService;
    @Resource
    private LockService lockService;
    @Resource
    private UserBankMapper userBankMapper;
    @Resource
    private AccountService accountService;
    @Resource
    private ConfigureService configureService;
    @Resource
    private UserFreezeMapper userFreezeMapper;

    @Override
    public GenericMapper<Cash, Integer> _getMapper() {
        return cashMapper;
    }

//    @Override
//    public void doMmmCashBack(MmmCash model) {
//        try {
//            // 查询用户账户
//            Account account = accountMapper.selectByMmmId(model.getWithdrawMoneymoremore());
//            if (account == null) {
//                throw new BussinessException("用户账户信息查询失败");
//            }
//
//            // 提现订单号
//            String orderNo = model.getOrderNo();
//
//            final Cash cash = cashMapper.selectByOrderNo(orderNo);
//            if (cash == null) {
//                throw new BussinessException("双乾提现回调处理失败，提现订单不存在，订单号：" + orderNo);
//            }
//
//
//            Cash uc = new Cash(t -> {
//                t.setId(cash.getId());
//                t.setVersion(cash.getVersion());
//            });
//            if ("88".equals(model.getResultCode())) {
//                // 双乾返回提现成功，扣除冻结金额
//                if (Cash.STATUS.T1.code == cash.getStatus() || Cash.STATUS.T2.code == cash.getStatus() || Cash.STATUS.T3.code == cash.getStatus()) {
//                    // 订单为待出账状态，进行成功出账处理（讲道理，走到这个分支 状态应该不可能是 T1/T2，但万一呢是吧）
//                    int count = accountMapper.updateAccount(cash.getAmount().negate(), BigDecimal.ZERO, cash.getAmount().negate(), cash.getUserId());
//                    if (count != 1) throw new BussinessException("双乾提现回调处理失败，处理账户资金失败，订单号：" + orderNo);
//
//                    // 记录资金记录
//                    String remark = "提现扣款，提现金额：" + cash.getAmount() + "元，手续费" + model.getFeeWithdraws() + "元。";
//                    AccountLog log = new AccountLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T9, account, remark);
//                    accountLogMapper.insert(log);
//
//                    // 更新提现记录
//                    uc.setActualArrival(cash.getAmount());
//                    if (StrUtil.isNotBlank(model.getFeeWithdraws())) {
//                        uc.setFee(new BigDecimal(model.getFeeWithdraws()));
//                        uc.setActualArrival(cash.getAmount().subtract(new BigDecimal(model.getFeeWithdraws())).setScale(2, BigDecimal.ROUND_HALF_UP));
//                    }
//                    if (StrUtil.isNotBlank(model.getFee())) {
//                        uc.setFeePlat(new BigDecimal(model.getFee()));
//                    }
//                    uc.setStatus(Cash.STATUS.T4.code);
//                    uc.setOutOrderNo(model.getLoanNo());
//                    uc.setMmmStatus(model.getResultCode());
//                    uc.setMmmMsg(JsonUtils.toJson(model));
//                    int i1 = cashMapper.updateByIdAndVersionSelective(uc);
//                    if (i1 != 1) throw new BussinessException("双乾提现回调处理失败，更新提现记录失败，订单号：" + orderNo);
//
//                    // 缓存回调结果
//                    redisService.put(CacheID.LKL_RESULT + model.getRemark1(), MmmResult.success("恭喜您，提现成功！"), 30 * 60);
//                } else if (cash.getStatus() == Cash.STATUS.T6.code) {
//                    // 该笔提现已取消，调用解冻接口
//                    MmmTransferAudit audit = MmmHelper.transferAudit(model.getLoanNo(), MmmAuditType.T6, MmmURL.NOTIFY_PRINT_SUCCESS, MmmURL.NOTIFY_PRINT_SUCCESS);
//                    // 缓存回调结果
//                    redisService.put(CacheID.LKL_RESULT + model.getRemark1(), MmmResult.success("提现失败，该笔提现已超时取消，订单号：" + cash.getOrderNo()), 30 * 60);
//                } else {
//                    throw new BussinessException("双乾提现回调处理，该笔提现订单已处理，订单号：" + orderNo);
//                }
//            } else if ("90".equals(model.getResultCode())) {
//                // 双乾返回待平台审核，如果该笔提现需要审核则此处不做处理，如果不需要审核则这里自动调用双乾审核接口进行审核通过
//                String cashMsg = "恭喜您，提现申请成功，请耐心等待后台审核！";
//                if (cash.getStatus() == Cash.STATUS.T6.code) {
//                    // 该笔提现已取消，调用解冻接口
//                    MmmTransferAudit audit = MmmHelper.transferAudit(model.getLoanNo(), MmmAuditType.T6, MmmURL.CASH_AUDIT_RETURN, MmmURL.CASH_AUDIT_NOTIFY);
//
//                    uc.setOutOrderNo(model.getLoanNo());
//                    uc.setMmmStatus(model.getResultCode());
//                    uc.setMmmMsg(JsonUtils.toJson(model));
//
//                    int i1 = cashMapper.updateByIdAndVersionSelective(uc);
//                    if (i1 != 1) throw new BussinessException("双乾提现回调处理失败，更新提现记录失败，订单号：" + orderNo);
//
//                    // 缓存回调结果
//                    redisService.put(CacheID.LKL_RESULT + model.getRemark1(), MmmResult.success("提现失败，该笔提现已超时取消，订单号：" + cash.getOrderNo()), 30 * 60);
//                    return;
//                }
//
//                // 提现是否需要后台人工审核
//                Integer needAudit = cash.getNeedAudit();
//
//                if (Cash.NEEDAUDIT.T2.code == needAudit) {
//                    // 该笔提现不需要后台人工审核，自动调用双乾审核接口进行审核
//                    MmmTransferAudit audit = MmmHelper.transferAudit(model.getLoanNo(), MmmAuditType.T5, MmmURL.CASH_AUDIT_RETURN, MmmURL.CASH_AUDIT_NOTIFY);
//                    if ("88".equals(audit.getResultCode())) {
//                        cashMsg = "恭喜您，提现成功！";
//                        // 更新提现状态
//                        int c = cashMapper.updateCashStatus(cash.getId(), Cash.STATUS.T3.code, Cash.STATUS.T1.code);
//                        if (c != 1) throw new BussinessException("提现回调，更新提现状态失败，订单号：" + cash.getOrderNo());
//                    } else {
//                        // 更新提现状态
//                        int c = cashMapper.updateCashStatus(cash.getId(), Cash.STATUS.T2.code, Cash.STATUS.T1.code);
//                        if (c != 1) throw new BussinessException("提现回调，更新提现状态失败，订单号：" + cash.getOrderNo());
//                    }
//                } else {
//                    // 更新提现状态
//                    int c = cashMapper.updateCashStatus(cash.getId(), Cash.STATUS.T2.code, Cash.STATUS.T1.code);
//                    if (c != 1) throw new BussinessException("提现回调，更新提现状态失败，订单号：" + cash.getOrderNo());
//                }
//
//
//                uc.setActualArrival(cash.getAmount());
//                if (StrUtil.isNotBlank(model.getFeeWithdraws())) {
//                    uc.setFee(new BigDecimal(model.getFeeWithdraws()));
//                    uc.setActualArrival(cash.getAmount().subtract(new BigDecimal(model.getFeeWithdraws())).setScale(2, BigDecimal.ROUND_HALF_UP));
//                }
//                if (StrUtil.isNotBlank(model.getFee())) {
//                    uc.setFeePlat(new BigDecimal(model.getFee()));
//                }
//                uc.setOutOrderNo(model.getLoanNo());
//                uc.setMmmStatus(model.getResultCode());
//                uc.setMmmMsg(JsonUtils.toJson(model));
//
//                int i1 = cashMapper.updateByIdAndVersionSelective(uc);
//                if (i1 != 1) throw new BussinessException("双乾提现回调处理失败，更新提现记录失败，订单号：" + orderNo);
//
//                // 缓存回调结果
//                redisService.put(CacheID.LKL_RESULT + model.getRemark1(), MmmResult.success(cashMsg), 30 * 60);
//            } else if ("89".equals(model.getResultCode())) {
//                // 双乾返回资金退回，标识提现失败，解冻用户平台账户资金
//
//                if (Cash.STATUS.T1.code == cash.getStatus() || Cash.STATUS.T2.code == cash.getStatus() || Cash.STATUS.T3.code == cash.getStatus()) {
//                    // 进行失败处理（讲道理，走到这个分支 状态应该不可能是 T3，但万一呢是吧）
//                    int count = accountMapper.updateAccount(BigDecimal.ZERO, cash.getAmount(), cash.getAmount().negate(), cash.getUserId());
//                    if (count != 1) {
//                        throw new BussinessException("双乾提现回调处理失败，处理账户资金失败，订单号：" + orderNo);
//                    }
//
//                    // 记录资金记录
//                    String remark = "提现解冻，解冻金额：" + cash.getAmount() + "元。";
//                    AccountLog log = new AccountLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T8, account, remark);
//                    accountLogMapper.insert(log);
//
//                    // 更新提现记录
//                    uc.setStatus(Cash.STATUS.T5.code);
//                    uc.setOutOrderNo(model.getLoanNo());
//                    uc.setMmmStatus(model.getResultCode());
//                    uc.setMmmMsg(JsonUtils.toJson(model));
//                    int i1 = cashMapper.updateByIdAndVersionSelective(uc);
//                    if (i1 != 1) throw new BussinessException("双乾提现回调处理失败，更新提现记录失败，订单号：" + orderNo);
//
//                    // 缓存回调结果
//                    redisService.put(CacheID.LKL_RESULT + model.getRemark1(), MmmResult.failed(model.getMessage()), 30 * 60);
//                } else if (Cash.STATUS.T4.code == cash.getStatus()) {
//                    // 订单提现成功状态，纠正客户资金 +可用  +总额
//                    int count = accountMapper.updateAccount(cash.getAmount(), cash.getAmount(), BigDecimal.ZERO, cash.getUserId());
//                    if (count != 1) {
//                        throw new BussinessException("双乾提现回调处理失败，处理账户资金失败，订单号：" + orderNo);
//                    }
//
//                    // 记录资金记录
//                    String remark = "提现退回，退回金额：" + cash.getAmount() + "元。";
//                    AccountLog log = new AccountLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T10, account, remark);
//                    accountLogMapper.insert(log);
//
//                    // 更新提现记录
//                    uc.setStatus(Cash.STATUS.T5.code);
//                    uc.setOutOrderNo(model.getLoanNo());
//                    uc.setMmmStatus(model.getResultCode());
//                    uc.setMmmMsg(JsonUtils.toJson(model));
//                    int i1 = cashMapper.updateByIdAndVersionSelective(uc);
//                    if (i1 != 1) throw new BussinessException("双乾提现回调处理失败，更新提现记录失败，订单号：" + orderNo);
//                } else {
//                    throw new BussinessException("双乾提现回调处理，该笔提现订单已处理，订单号：" + orderNo);
//                }
//            } else {
//                // 双乾返回提现失败，修改订单状态为失败，并且解冻资金
//                if (Cash.STATUS.T1.code == cash.getStatus() || Cash.STATUS.T2.code == cash.getStatus() || Cash.STATUS.T3.code == cash.getStatus()) {
//                    // 进行失败处理（讲道理，走到这个分支 状态应该不可能是 T3，但万一呢是吧）
//                    int count = accountMapper.updateAccount(BigDecimal.ZERO, cash.getAmount(), cash.getAmount().negate(), cash.getUserId());
//                    if (count != 1) {
//                        throw new BussinessException("双乾提现回调处理失败，处理账户资金失败，订单号：" + orderNo);
//                    }
//
//                    // 记录资金记录
//                    String remark = "提现解冻，解冻金额：" + cash.getAmount() + "元。";
//                    AccountLog log = new AccountLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T8, account, remark);
//                    accountLogMapper.insert(log);
//
//                    // 更新提现状态
//                    int c = cashMapper.updateCashStatus(cash.getId(), Cash.STATUS.T5.code, Cash.STATUS.T1.code);
//                    if (c != 1) throw new BussinessException("提现回调，更新提现状态失败，订单号：" + cash.getOrderNo());
//
//                    // 更新提现记录
//                    uc.setOutOrderNo(model.getLoanNo());
//                    uc.setMmmStatus(model.getResultCode());
//                    uc.setMmmMsg(JsonUtils.toJson(model));
//                    int i1 = cashMapper.updateByIdAndVersionSelective(uc);
//                    if (i1 != 1) throw new BussinessException("双乾提现回调处理失败，更新提现记录失败，订单号：" + orderNo);
//
//                }
//                // 缓存回调结果
//                redisService.put(CacheID.LKL_RESULT + model.getRemark1(), MmmResult.failed(model.getMessage()), 30 * 60);
//            }
//        } catch (BussinessException e) {
//            // 缓存回调结果
//            redisService.put(CacheID.LKL_RESULT + model.getRemark1(), MmmResult.failed(e.getMessage()), 30 * 60);
//            throw e;
//        } catch (Exception e) {
//            // 缓存回调结果
//            redisService.put(CacheID.LKL_RESULT + model.getRemark1(), MmmResult.failed("系统繁忙"), 30 * 60);
//            throw e;
//
//        }
//    }

//    @Override
//    public void doMmmCashAuditBack(MmmTransferAudit model) {
//        // 提现订单号
//        String loanNo = model.getLoanNoList();
//        Cash cash = cashMapper.selectByLoanNo(loanNo);
//        if (cash == null) {
//            throw new BussinessException("双乾提现回调处理失败，提现订单不存在，三方订单号：" + loanNo);
//        }
//        // 查询用户账户
//        Account account = accountMapper.selectByUID(cash.getUserId());
//        if (account == null) {
//            throw new BussinessException("用户账户信息查询失败");
//        }
//
//        Cash uc = new Cash(t -> {
//            t.setId(cash.getId());
//            t.setVersion(cash.getVersion());
//        });
//
//        if ("88".equals(model.getResultCode())) {
//            if (MmmAuditType.T6.equals(model.getAuditType())) {
//                // 解冻用户资金
//                if (Cash.STATUS.T6.code == cash.getStatus()) {
//                    // 不处理
//                } else if (Cash.STATUS.T2.code == cash.getStatus()) {
//                    // 退回资金
//                    // 解冻用户冻结资金
//                    int count = accountMapper.updateAccount(BigDecimal.ZERO, cash.getAmount(), cash.getAmount().negate(), cash.getUserId());
//                    if (count != 1) throw new BussinessException("提现审核失败，处理账户资金失败，订单号：" + cash.getOrderNo());
//
//                    // 记录资金记录
//                    String remark = "提现失败，解冻金额：" + cash.getAmount() + "元。";
//                    AccountLog log = new AccountLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T7, account, remark);
//                    accountLogMapper.insert(log);
//
//                    // 更新提现状态
//                    int c = cashMapper.updateCashStatus(cash.getId(), Cash.STATUS.T5.code, Cash.STATUS.T2.code);
//                    if (c != 1) throw new BussinessException("提现回调，更新提现状态失败，订单号：" + cash.getOrderNo());
//                } else if (Cash.STATUS.T3.code == cash.getStatus()) {
//                    // 退回资金
//                    // 解冻用户冻结资金
//                    int count = accountMapper.updateAccount(BigDecimal.ZERO, cash.getAmount(), cash.getAmount().negate(), cash.getUserId());
//                    if (count != 1) throw new BussinessException("提现审核失败，处理账户资金失败，订单号：" + cash.getOrderNo());
//
//                    // 记录资金记录
//                    String remark = "提现失败，解冻金额：" + cash.getAmount() + "元。";
//                    AccountLog log = new AccountLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T7, account, remark);
//                    accountLogMapper.insert(log);
//
//                    // 更新提现状态
//                    int c = cashMapper.updateCashStatus(cash.getId(), Cash.STATUS.T5.code, Cash.STATUS.T3.code);
//                    if (c != 1) throw new BussinessException("提现回调，更新提现状态失败，订单号：" + cash.getOrderNo());
//                }
//
//                // 更新提现记录
//                uc.setMmmAuditStatus(model.getResultCode());
//                uc.setMmmAuditMsg(JsonUtils.toJson(model));
//                uc.setRemark("审核不通过-提现失败");
//                int i1 = cashMapper.updateByIdAndVersionSelective(uc);
//                if (i1 != 1) throw new BussinessException("双乾提现审核回调处理失败，更新提现记录失败，三方订单号：" + loanNo);
//
//            } else if (MmmAuditType.T5.equals(model.getAuditType())) {
//                // 解冻用户资金
//                if (Cash.STATUS.T6.code == cash.getStatus()) {
//                    // 扣除金额
//
//                    int count = accountMapper.updateAccount(cash.getAmount().negate(), cash.getAmount().negate(), BigDecimal.ZERO, cash.getUserId());
//                    if (count != 1) throw new BussinessException("双乾提现回调处理失败，处理账户资金失败，三方订单号：" + loanNo);
//
//                    // 记录资金记录
//                    String remark = "提现扣款，提现金额：" + cash.getAmount() + "元，手续费" + cash.getFee() + "元。";
//                    AccountLog log = new AccountLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T9, account, remark);
//                    accountLogMapper.insert(log);
//
//                    // 更新提现状态
//                    int c = cashMapper.updateCashStatus(cash.getId(), Cash.STATUS.T4.code, Cash.STATUS.T6.code);
//                    if (c != 1) throw new BussinessException("提现回调，更新提现状态失败，订单号：" + cash.getOrderNo());
//                } else if (Cash.STATUS.T2.code == cash.getStatus()) {
//                    int count = accountMapper.updateAccount(cash.getAmount().negate(), BigDecimal.ZERO, cash.getAmount().negate(), cash.getUserId());
//                    if (count != 1) throw new BussinessException("双乾提现回调处理失败，处理账户资金失败，三方订单号：" + loanNo);
//
//                    // 记录资金记录
//                    String remark = "提现扣款，提现金额：" + cash.getAmount() + "元，手续费" + cash.getFee() + "元。";
//                    AccountLog log = new AccountLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T9, account, remark);
//                    accountLogMapper.insert(log);
//
//                    // 更新提现状态
//                    int c = cashMapper.updateCashStatus(cash.getId(), Cash.STATUS.T4.code, Cash.STATUS.T2.code);
//                    if (c != 1) throw new BussinessException("提现回调，更新提现状态失败，订单号：" + cash.getOrderNo());
//                } else if (Cash.STATUS.T3.code == cash.getStatus()) {
//                    int count = accountMapper.updateAccount(cash.getAmount().negate(), BigDecimal.ZERO, cash.getAmount().negate(), cash.getUserId());
//                    if (count != 1) throw new BussinessException("双乾提现回调处理失败，处理账户资金失败，三方订单号：" + loanNo);
//
//                    // 记录资金记录
//                    String remark = "提现扣款，提现金额：" + cash.getAmount() + "元，手续费" + cash.getFee() + "元。";
//                    AccountLog log = new AccountLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T9, account, remark);
//                    accountLogMapper.insert(log);
//
//                    // 更新提现状态
//                    int c = cashMapper.updateCashStatus(cash.getId(), Cash.STATUS.T4.code, Cash.STATUS.T3.code);
//                    if (c != 1) throw new BussinessException("提现回调，更新提现状态失败，订单号：" + cash.getOrderNo());
//                }
//
//                // 更新提现记录
//                uc.setMmmAuditStatus(model.getResultCode());
//                uc.setMmmAuditMsg(JsonUtils.toJson(model));
//                uc.setRemark("审核通过-提现成功");
//                int i1 = cashMapper.updateByIdAndVersionSelective(uc);
//                if (i1 != 1) throw new BussinessException("双乾提现审核回调处理失败，更新提现记录失败，三方订单号：" + loanNo);
//            }
//
//        } else if ("87".equals(model.getResultCode())) {
//            // 处理中，平台不处理
//        } else {
//            // 审核失败，平台不处理，等待后续对账查询接触针对处理
//        }
//    }

//    @Override
//    public void doAudit(CashModel model) throws Exception {
//        Cash cash = cashMapper.selectByPrimaryKey(model.getId());
//        if (cash == null) {
//            throw new BussinessException("提现订单不存在");
//        } else if (cash.getStatus() != Cash.STATUS.T2.code) {
//            throw new BussinessException("该订单状态不可审核");
//        }
//        Cash uc = new Cash(t -> {
//            t.setId(cash.getId());
//            t.setVersion(cash.getVersion());
//        });
//        uc.setRemark(model.getRemark());
//
//        cashMapper.updateByIdAndVersionSelective(uc);
//        if ("1".equals(model.getAuditStatus())) {
//            // 通过
//            int i1 = cashMapper.updateCashStatus(cash.getId(), Cash.STATUS.T3.code, Cash.STATUS.T2.code);
//            if (i1 != 1) throw new BussinessException("审核失败，更新提现记录失败");
//
//            PayUpload payUpload = PaymaxPayUtils.payV2(cash);
//            log.info("审核结果：" + JsonUtils.toJson(payUpload));
//            if (!payUpload.getReqSuccessFlag())
//                throw new BussinessException("调用代付接口提示失败，错误码：" + payUpload.getFailureMsg() + "，错误消息：" + payUpload.getFailureMsg());
//        } else {
//            // 不通过
//            int i1 = cashMapper.updateCashStatus(cash.getId(), Cash.STATUS.T5.code, Cash.STATUS.T2.code);
//            if (i1 != 1) throw new BussinessException("审核失败，更新提现记录失败");
//
//        }
//    }

    @Override
    public void doAudit(CashModel model, String apiUrl) throws Exception {
        // 提现参数校验
        Cash cash = cashMapper.selectByPrimaryKey(model.getId());
        if (null == cash) {
            throw new BussinessException("提现记录不存在");
        }
        if (cash.getStatus() != Cash.STATUS.T2.code) {
            throw new BussinessException("提现申请状态已更改请刷新后重试");
        }
        //更新提现订单信息
        User user = userMapper.selectByPrimaryKey(cash.getUserId());

        List<UserBank> banks = userBankMapper.select(new UserBank(ub -> {
            ub.setBankNo(cash.getBankNo());
        }));
        if (CollectionUtils.isEmpty(banks)) {
            throw new BussinessException("银行卡不存在");
        }
        UserBank userBank = banks.get(0);
        //根据审核状态通过，则调第三方提现接口，不通过，解冻提现金额
        if (Integer.valueOf(model.getAuditStatus()) == CashModel.AUDITSTATUS.T1.code) {
            String result = doumpaycash(user, userBank, model.getAmount(), apiUrl, cash.getFee());
            if (!result.equals(ResultCode.RESULT_MSG_CASHING)) {
                throw new BussinessException(result);
            }
        } else {
            cash.setStatus(Cash.STATUS.T5.code);
            cash.setRemark(model.getRemark());
            int count = cashMapper.updateByPrimaryKeySelective(cash);
            //解冻用户资金账户
            accountMapper.updateAccount(BigDecimal.ZERO, cash.getAmount(), cash.getAmount().negate(), cash.getUserId());
            Account account = accountMapper.selectByUID(cash.getUserId());
            //资金记录
            accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T8, account, "提现解冻，解冻金额：" + cash.getAmount() + "元。"));
        }
    }

    @Override
    public Map<String, String> doCash(User user, Integer bankId, BigDecimal amount, String apiUrl) {

        if (lockService.lock(LockId.CASH + user.getId())) {
            throw new BussinessException("您提交的提现请求正在处理，请勿重复提交");
        }
        try {
            UserFreeze uFreezes = userFreezeMapper.selectOne(new UserFreeze(uf -> {
                uf.setUserId(user.getId());
                uf.setDelFlag(UserFreeze.DELFLAG.NORMAL.code);
            }));
            if (uFreezes.getFreezeCash() == UserFreeze.STATUS.T2.code) {
                throw new BussinessException("用户提现已冻结，请先解冻");
            }
            List<UserBank> list = userBankMapper.select(new UserBank(t -> {
                t.setId(bankId);
                t.setUserId(user.getId());
            }));
            if (CollectionUtils.isEmpty(list)) {
                throw new BussinessException("银行卡不存在");
            }
            // 查询用户账户信息
            Account account = accountMapper.selectByUID(user.getId());
            if (account == null) {
                throw new BussinessException("查询用户账户信息失败");
            }
            UserBank bank = list.get(0);
            // 提现参数校验
            checkCash(user, amount);

            // 冻结用户资金，并记录资金日志
            int c1 = accountMapper.updateAccount(BigDecimal.ZERO, amount.negate(), amount, user.getId());
            if (c1 != 1) {
                throw new BussinessException("提现更新账户信息失败，账户余额不足");
            }

            Account acc = accountMapper.selectByUID(user.getId());
            String remark = "提现申请，冻结金额" + amount + "元。";
            accountLogMapper.insert(AccountLog.buildLog(user.getId(), amount, AccountLog.TYPE.T2, acc, remark));

            BigDecimal cashFeeRatio = redisService.get(ConfigNID.CASH_FEE_RATIO, BigDecimal.class);
            if (cashFeeRatio == null) {
                cashFeeRatio = BigDecimal.ZERO;
            }
            BigDecimal cashFeeMin = redisService.get(ConfigNID.CASH_FEE_MIN, BigDecimal.class);
            if (cashFeeMin == null) {
                cashFeeMin = new BigDecimal(0);// 默认单笔提现最低手续费为0元
            }
            BigDecimal cashFee = cashFeeRatio.multiply(amount).multiply(BigDecimal.valueOf(0.01));
            if (cashFeeMin.compareTo(cashFee) > 0) {
                cashFee = cashFeeMin;
            }
            // 记录提现订单
            String orderNo = OrderNoUtils.getSerialNumber();
            Cash model = new Cash();
            model.setUserId(user.getId());
            model.setRealName(user.getRealName());
            model.setIdCard(user.getIdCard());
            model.setBankNo(bank.getBankNo());
            model.setBranch(bank.getBranch());
            model.setBankName(bank.getBankName());
            model.setBankCode(bank.getBankCode());
            model.setOrderNo(orderNo);
            model.setAmount(amount);
            model.setType(Cash.TYPE.ONLINE.code);
            model.setFee(cashFee);
            Map<String, String> map = new HashMap<>();
            int needAudit = redisService.get(ConfigNID.CASH_NEED_AUDIT, Integer.class);
            if (needAudit == Cash.NEEDAUDIT.T1.code) {
                // 需要审核
                model.setStatus(Cash.STATUS.T2.code);
                model.setNeedAudit(Cash.NEEDAUDIT.T1.code);
                cashMapper.insert(model);
                map.put("needAudit", String.valueOf(Cash.NEEDAUDIT.T1.code));
                map.put("resMsg", "提现申请成功");
                return map;
            } else {
                // 不需要审核
                model.setStatus(Cash.STATUS.T3.code);
                model.setNeedAudit(Cash.NEEDAUDIT.T2.code);
                cashMapper.insert(model);
                //第三方提现请求
                String resMsg = doumpaycash(user, bank, amount, apiUrl, cashFee);
                map.put("needAudit", String.valueOf(Cash.NEEDAUDIT.T2.code));
                map.put("resMsg", resMsg);
                return map;
            }
        } finally {
            // 释放锁
            lockService.unlock(LockId.CASH + user.getId());

        }
    }

    private String doumpaycash(User user, UserBank userBank, BigDecimal amount, String apiUrl, BigDecimal fee) {
        //构建请求参数
        //第三方提现的金额是=提现金额-平台手续费
        BigDecimal amo = amount.subtract(fee);
        Map<String, Object> params = new HashMap<>(30);
        //接口名称
        params.put("service", UmfEndPoint.service_fukuan);
        params.put("charset", "UTF-8");
        //商户编号
        params.put("mer_id", UmfEndPoint.MERCHANT_ID);
        params.put("sign_type", "RSA");
        //付款请求服务器异步通知地址
        params.put("notify_url", redisService.get(ConfigNID.WEB_SERVER_URL) + apiUrl + "/pay/fuKuanResultNotify");
        //响应数据格式
        params.put("res_format", "HTML");
        params.put("version", "4.0");
        String orderId = OrderNoUtils.getCashOrderNo();
        params.put("order_id", orderId);
        params.put("mer_date", DateFormatUtils.format(new Date(), "yyyyMMdd"));
        //金额以分为单位 所以这里乘以100
        params.put("amount", (BigDecimalUtils.mul(amo, 100d)).intValue() + "");
        //收款方账户类型 00 银行卡 02 U付
        params.put("recv_account_type", "00");
        //收款方账户属性 0-对私  1-对公
        params.put("recv_bank_acc_pro", "0");
        //收款方账号
        params.put("recv_account", userBank.getBankNo());
        //收款方户名
        params.put("recv_user_name", userBank.getRealName());
        //收款方证件类型 身份证 01
        params.put("identity_type", "01");
        //收款方平台预留证件号码
        params.put("identity_code", userBank.getIdCard());
        //证件持有人真实姓名
        params.put("identity_holder", userBank.getRealName());
        //商户用户标识 其实就是userId
        params.put("mer_cust_id", user.getId().toString());
        //媒介类型
        params.put("media_type", "");
        //付款方平台预留手机号码
        params.put("media_id", userBank.getMobile());
        //收款方账户类型为00且收款方账户属性为1(对私)时必填
        params.put("recv_gate_id", "");
        //摘要 收款方账户类型为00时必填（不能超过超过10个汉字，多余将拒绝）
        params.put("purpose", "用户" + user.getUserName() + "提现" + amount + "元");
        params.put("prov_name", "");
        params.put("city_name", "");
        //收款方账户类型为00时必填 开户行支行全称
        params.put("bank_brhname", userBank.getBranch());
        //付款实时和非实时标识 0：实时付款产品此字段要填写为0【需要开通实时付款产品】   1：非实时付款此字段为1【默认为1】
        params.put("checkFlag", "0");
        //付款成功后，将给此号码下发转账成功短信。仅开通此功能的商户有效。
        params.put("mobile_no", userBank.getMobile());
        ReqData reqData;
        Map resData = new HashMap(10);
        try {
            //生成post请求对象
            reqData = Mer2Plat_v40.makeReqDataByGet(params);
            String responseStr = UmfEndPoint.doFuKuanRequest(reqData);
            if (StringUtils.isNotBlank(responseStr)) {
                resData = Plat2Mer_v40.getResData(responseStr);
            }
            if (resData.get(UmfCommon.RET_CODE).equals(ResultCode.RESULT_CODE_OK)) {
                return ResultCode.RESULT_MSG_CASHING;
            } else {
                return resData.get(UmfCommon.RET_MSG).toString();
            }
        } catch (ReqDataException | RetDataException e) {
            e.printStackTrace();
            return "接口调用异常,请查看日志";
        }
    }

    @Override
    public void checkCash(User user, BigDecimal amount) {
        // 校验提现金额
        if (amount == null || amount.compareTo(BigDecimal.ZERO) != 1) {
            throw new BussinessException("提现金额有误");
        }
        amount = amount.setScale(2, BigDecimal.ROUND_HALF_UP);

        // 校验最低提现限额
        AccountModel model = accountService.getAccountModel(user.getId());
        if (model.getCashMin().compareTo(amount) > 0) {
            throw new BussinessException("提现金额小于单笔最低提现限额（" + model.getCashMin() + "元）");
        }

        // 校验最高提现限额
        if (model.getCashMax().compareTo(amount) < 0) {
            throw new BussinessException("提现金额大于单笔最高提现限额（" + model.getCashMax() + "元）");
        }

        //校验单日提现最大次数
        Map<String, Object> param = new HashMap<>();
        param.put("delFlag", AccountLog.DELFLAG.NORMAL.code);
        param.put("userId", user.getId());
        param.put("type", AccountLog.TYPE.T2.code);
        param.put("type2", AccountLog.TYPE.T9.code);
        param.put("createTime", new Date());
        Integer maxNum = accountLogMapper.countByTime(param);
        Integer cashDailyCount = redisService.get(ConfigNID.CASH_DAILY_COUNT, Integer.class);
        if (maxNum.intValue() > cashDailyCount.intValue()) {
            throw new BussinessException("今日提现次数大于单日提现最大次数（" + cashDailyCount + "次）");
        }

        //校验单日提现最大总额
        BigDecimal sumAmount = accountLogMapper.sumAmountByTime(param);
        if (sumAmount == null) {
            sumAmount = BigDecimal.ZERO;
        }
        BigDecimal cashDailyAmount = redisService.get(ConfigNID.CASH_DAILY_AMOUNT, BigDecimal.class);
        if (sumAmount.compareTo(cashDailyAmount) > 0) {
            throw new BussinessException("今日提现总额大于单日提现最大总额（" + cashDailyAmount + "元）");
        }

        //校验用户手续费
        BigDecimal cashFee = model.getCashFeeRatio().multiply(amount);
        if (model.getCashFeeMin().compareTo(cashFee) > 0) {
            cashFee = model.getCashFeeMin();
        }
        if (cashFee.compareTo(amount) > 0) {
            throw new BussinessException("提现金额小于最小提现手续费(" + cashFee + "元）");
        }

        // 校验用余额
        Account account = accountMapper.selectByUID(user.getId());
        if (account == null) {
            throw new BussinessException("查询用户账户失败");
        }

        if (amount.compareTo(account.getAvailable()) > 0) {
            throw new BussinessException("提现申请失败，您的账户余额不足！");
        }

    }

    @Override
    public void doCancel(Integer id) {
        final Cash cash = cashMapper.selectByPrimaryKey(id);
        if (cash == null) {
            throw new BussinessException("提现订单不存在");
        }
        if (!cash.getStatus().equals(Cash.STATUS.T1.code)) {
            throw new BussinessException("订单当前状态不能取消");
        }

        final Account account = accountMapper.selectByUID(cash.getUserId());
        if (account == null) {
            throw new BussinessException("查询用户账户失败");
        }

        // 更新订单状态为 取消提现
        int i1 = cashMapper.updateCashStatus(id, Cash.STATUS.T6.code, Cash.STATUS.T1.code);
        if (i1 != 1) {
            throw new BussinessException("取消提现失败，更新提现记录失败");
        }

        // 解冻用户冻结资金
        int count = accountMapper.updateAccount(BigDecimal.ZERO, cash.getAmount(), cash.getAmount().negate(), cash.getUserId());
        if (count != 1) {
            throw new BussinessException("取消提现，处理账户资金失败，订单号：" + cash.getOrderNo());
        }

        // 记录资金记录
        String remark = "提现取消，解冻金额：" + cash.getAmount() + "元。";
        AccountLog log = new AccountLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T8, account, remark);
        accountLogMapper.insert(log);
    }

    @Override
    public void handCash(Cash cash) {

        Cash cash1 = cashMapper.selectOne(new Cash(c -> {
            c.setOutOrderNo(cash.getOutOrderNo());
        }));
        if (null != cash1) {
            throw new BussinessException("订单号已存在，请重新填写！");
        }
        String orderNo = OrderNoUtils.getSerialNumber();
        cash.setOrderNo(orderNo);
        cash.setActualArrival(cash.getAmount());
        cash.setFee(BigDecimal.ZERO);
        cash.setFeePlat(BigDecimal.ZERO);
        cash.setStatus(Cash.STATUS.T4.code);
        cash.setDelFlag(Cash.DELFLAG.NORMAL.code);
        cash.setCreateTime(new Date());
        cashMapper.insert(cash);
        UserFreeze uFreezes = userFreezeMapper.selectOne(new UserFreeze(uf -> {
            uf.setUserId(cash.getUserId());
            uf.setDelFlag(UserFreeze.DELFLAG.NORMAL.code);
        }));
        if (uFreezes.getFreezeCash().intValue() == UserFreeze.STATUS.T2.code) {
            throw new BussinessException("用户提现已冻结，请解冻！");
        }
        Account account1 = accountMapper.selectByUID(cash.getUserId());
        if (account1.getAvailable().compareTo(cash.getAmount()) < 0) {
            throw new BussinessException("出金金额大于可用金额");
        }
        //减资金
        accountMapper.updateAccount(cash.getAmount().multiply(new BigDecimal(-1)), cash.getAmount().multiply(new BigDecimal(-1)), BigDecimal.ZERO, cash.getUserId());
        Account account = accountMapper.selectByUID(cash.getUserId());
        //资金记录
        accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T13, account, "手动出金：" + cash.getAmount() + "元"));
    }

    @Override
    public BigDecimal selectSumAmountByStatus(Integer status, String startTime, String endTime, Integer agentId) {
        Map<String, Object> param = new HashMap<>();
        param.put("status", status);
        param.put("startTime", startTime);
        param.put("endTime", endTime);
        param.put("agentId", agentId);
        return cashMapper.selectSumAmountByStatus(param);

    }

    @Override
    public long countByStatus(Integer status, String startTime, String endTime, Integer agentId) {
        Map<String, Object> param = new HashMap<>();
        param.put("status", status);
        param.put("startTime", startTime);
        param.put("endTime", endTime);
        param.put("agentId", agentId);
        return cashMapper.countByStatus(param);
    }


    @Override
    public void handleCashByUmpay(String tradeNo, String orderId, String amount, String tradeState, String retMsg) {
        //主要业务参数判断
        if (StringUtils.isBlank(amount) || StringUtils.isBlank(orderId)) {
            log.error("处理订单参数缺失,终止处理...");
            return;
        }
        //通过订单号 用户id查询提现订单
        Cash cash = cashMapper.selectOne(new Cash(c -> {
            c.setOrderNo(orderId);
            c.setDelFlag(Cash.DELFLAG.NORMAL.code);
        }));
        if (Objects.equals(ResultCode.TradeStateEnum.TRADE_SUCCESS.getCode(), tradeState)) {
            //判断订单状态和订单金额
            if (null != cash && cash.getStatus() == Cash.STATUS.T3.code) {
                //转换后的订单金额
                BigDecimal actualarrival = cash.getAmount().divide(cash.getFee());
                BigDecimal transferAmount = BigDecimalUtils.mul(actualarrival, 100d);
                if (transferAmount.doubleValue() == new BigDecimal(amount).doubleValue()) {
                    //更新用户资金账户
                    accountMapper.updateAccount(cash.getAmount().negate(), BigDecimal.ZERO, cash.getAmount().negate(), cash.getUserId());
                    Account account = accountMapper.selectByUID(cash.getUserId());
                    //资金记录
                    accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T9, account, "提现扣除，扣除金额：" + cash.getAmount() + "元。"));
                    //处理提现订单
                    cash.setActualArrival(actualarrival);
                    cash.setUpdateTime(new Date());
                    cash.setOutOrderNo(tradeNo);
                    cash.setOutStatus(tradeState);
                    cash.setRemark("提现成功:[" + retMsg + "]");
                    cash.setOutMsg("提现成功:[" + retMsg + "]");
                    cash.setStatus(Recharge.STATUS.T3.code);
                    cashMapper.updateByPrimaryKeySelective(cash);
                }
            }
        } else {
            //解冻用户资金账户
            accountMapper.updateAccount(BigDecimal.ZERO, cash.getAmount(), cash.getAmount().negate(), cash.getUserId());
            Account account = accountMapper.selectByUID(cash.getUserId());
            //资金记录
            accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T8, account, "提现解冻，解冻金额：" + cash.getAmount() + "元。"));
            //处理提现订单
            cash.setUpdateTime(new Date());
            cash.setOutOrderNo(tradeNo);
            cash.setOutStatus(tradeState);
            cash.setRemark("提现失败:[" + retMsg + "]");
            cash.setOutMsg("提现失败:[" + retMsg + "]");
            cash.setStatus(Recharge.STATUS.T4.code);
            cashMapper.updateByPrimaryKeySelective(cash);
        }

    }

    @Override
    public void createCash(String bankCardId, BigDecimal money, User user) {
        if (lockService.lock(LockId.CASH + user.getId())) {
            throw new BussinessException("您提交的提现请求正在处理，请勿重复提交");
        }
        try {
            UserBank bank = userBankMapper.selectByPrimaryKey(Integer.valueOf(bankCardId));

            Account acc = accountMapper.selectByUID(user.getId());
            String remark = "提现申请，冻结金额" + money + "元。";
            accountLogMapper.insert(AccountLog.buildLog(user.getId(), money, AccountLog.TYPE.T2, acc, remark));

            // 冻结用户资金，并记录资金日志
            int c1 = accountMapper.updateAccount(BigDecimal.ZERO, money.negate(), money, user.getId());
            if (c1 != 1) {
                throw new BussinessException("提现更新账户信息失败，账户余额不足");
            }

            String orderNo = OrderNoUtils.getHRCashOrderNo();
//            BigDecimal cashFeeRatio = redisService.get(ConfigNID.CASH_FEE_RATIO, BigDecimal.class);
//            if (cashFeeRatio == null){
//                cashFeeRatio =BigDecimal.ZERO;
//            }
//            BigDecimal cashFeeMin = redisService.get(ConfigNID.CASH_FEE_MIN, BigDecimal.class);
//            if (cashFeeMin == null) {
//                cashFeeMin = new BigDecimal(0);// 默认单笔提现最低手续费为0元
//            }
//            BigDecimal cashFee = cashFeeRatio.multiply(money).multiply(BigDecimal.valueOf(0.01));
//            if(cashFeeMin.compareTo(cashFee)>0){
//                cashFee = cashFeeMin;
//            }
            Cash model = new Cash();
            model.setUserId(user.getId());
            model.setRealName(user.getRealName());
            model.setIdCard(user.getIdCard());
            model.setBankNo(bank.getBankNo());
            model.setBranch(bank.getBranch());
            model.setBankName(bank.getBankName());
            model.setBankCode(bank.getBankCode());
            model.setOrderNo(orderNo);
            model.setAmount(money);
            model.setType(Cash.TYPE.ONLINE.code);
            model.setFee(BigDecimal.ZERO);
            model.setStatus(Cash.STATUS.T2.code);
            model.setNeedAudit(Cash.NEEDAUDIT.T1.code);
            if (cashMapper.insert(model) != 1) throw new BussinessException("保存提现申请失败");
        } finally {
            // 释放锁
            lockService.unlock(LockId.CASH + user.getId());

        }
    }

    @Override
    public void doAuditLianLian(CashModel model) throws Exception {
        // 提现参数校验
        Cash cash = cashMapper.selectByPrimaryKey(model.getId());
        if (null == cash) {
            throw new BussinessException("提现记录不存在");
        }
        if (cash.getStatus() != Cash.STATUS.T2.code) {
            throw new BussinessException("提现申请状态已更改请刷新后重试");
        }
        //更新提现订单信息
        User user = userMapper.selectByPrimaryKey(cash.getUserId());

        List<UserBank> banks = userBankMapper.select(new UserBank(ub -> {
            ub.setBankNo(cash.getBankNo());
        }));
        if (CollectionUtils.isEmpty(banks)) {
            throw new BussinessException("银行卡不存在");
        }
        //根据审核状态通过，则调第三方提现接口，不通过，解冻提现金额
        if (Integer.valueOf(model.getAuditStatus()) == CashModel.AUDITSTATUS.T1.code) {

            // 调用第三方代付接口
            DaiFuResp daiFuResp = sendDaiFuNotifyByLianLian(cash);
            if (StringUtils.isNotBlank(daiFuResp.getStatus()) && daiFuResp.getStatus().equalsIgnoreCase(EPayConsts.RES_FLAG_SUCCESS)) {
                //修改订单状态
                cash.setStatus(Cash.STATUS.T3.code);
                cashMapper.updateByPrimaryKeySelective(cash);
            } else if (StringUtils.isNotBlank(daiFuResp.getStatus()) && daiFuResp.getStatus().equalsIgnoreCase(EPayConsts.RES_FLAG_UNKNOWN)) {
                cash.setStatus(Cash.STATUS.T3.code);
                cashMapper.updateByPrimaryKeySelective(cash);
//                result = StrKit.isBlank(daiFuResp.getRemark()) ? "请求结果未知" : daiFuResp.getRemark();
            } else {
//                this.doCashVerify(order.getId(), "failed", "3");
                throw new BussinessException(StringUtils.isBlank(daiFuResp.getRemark()) ? "第三方请求异常" : daiFuResp.getRemark());
            }
        } else {
            cash.setStatus(Cash.STATUS.T5.code);
            cash.setRemark(model.getRemark());
            int count = cashMapper.updateByPrimaryKeySelective(cash);
            //解冻用户资金账户
            accountMapper.updateAccount(BigDecimal.ZERO, cash.getAmount(), cash.getAmount().negate(), cash.getUserId());
            Account account = accountMapper.selectByUID(cash.getUserId());
            //资金记录
            accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T8, account, "提现解冻，解冻金额：" + cash.getAmount() + "元。"));
        }
    }

    @Override
    public void doAuditHR(CashModel model) throws Exception {
        // 提现参数校验
        Cash cash = cashMapper.selectByPrimaryKey(model.getId());
        if (null == cash) {
            throw new BussinessException("提现记录不存在");
        }
        if (cash.getStatus() != Cash.STATUS.T2.code) {
            throw new BussinessException("提现申请状态已更改请刷新后重试");
        }

        // 根据审核状态通过，则调第三方提现接口，不通过，解冻提现金额
        if (Integer.valueOf(model.getAuditStatus()) == CashModel.AUDITSTATUS.T1.code) {

            // 调用第三方代付接口

            String notifyUrl = redisService.get(ConfigNID.WEB_SERVER_URL) + "/api/notify/hr/dfNotify";
            Map<String, String> resMap = HRPayUtils.proxyPay(cash.getOrderNo(), notifyUrl, cash.getAmount(), cash.getRealName(), cash.getIdCard(), cash.getBankNo());
            if (!("0000".equals(resMap.get("respCode")) || "P000".equals(resMap.get("respCode")))) {
                // 代付失败
                int c1 = cashMapper.updateByPrimaryKeySelective(new Cash(t -> {
                    t.setId(cash.getId());
                    t.setUpdateTime(new Date());
                    t.setStatus(Cash.STATUS.T5.code);
                    t.setRemark(resMap.get("respDesc"));
                    t.setOutStatus(resMap.get("respCode"));
                    t.setOutMsg(JSON.toJSONString(resMap));
                }));
                if (c1 != 1) throw new BussinessException("更新提现记录失败");

                //资金记录
                Account account = accountMapper.selectByUID(cash.getUserId());
                int c2 = accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T8, account, "提现解冻，解冻金额：" + cash.getAmount() + "元。"));
                if (c2 != 1) throw new BussinessException("保存资金记录失败");
                //解冻用户资金账户
                int c3 = accountMapper.updateAccount(BigDecimal.ZERO, cash.getAmount(), cash.getAmount().negate(), cash.getUserId());
                if (c3 != 1) throw new BussinessException("更新用户账户信息失败");

            } else {
                // 代付提交成功
                int c1 = cashMapper.updateByPrimaryKeySelective(new Cash(t -> {
                    t.setId(cash.getId());
                    t.setUpdateTime(new Date());
                    t.setStatus(Cash.STATUS.T3.code);
                    t.setRemark(resMap.get("respDesc"));
                    t.setOutStatus(resMap.get("respCode"));
                    t.setOutMsg(JSON.toJSONString(resMap));
                }));
                if (c1 != 1) throw new BussinessException("更新提现记录失败");
            }

        } else {
            // 审核不通过
            if (cashMapper.updateByPrimaryKeySelective(new Cash(t -> {
                t.setId(cash.getId());
                t.setUpdateTime(new Date());
                t.setStatus(Cash.STATUS.T5.code);
                t.setRemark(model.getRemark());
            })) != 1) throw new BussinessException("更新提现记录失败");

            //资金记录
            Account account = accountMapper.selectByUID(cash.getUserId());
            int c1 = accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T8, account, "提现解冻，解冻金额：" + cash.getAmount() + "元。"));
            if (c1 != 1) throw new BussinessException("保存资金记录失败");
            //解冻用户资金账户
            int c2 = accountMapper.updateAccount(BigDecimal.ZERO, cash.getAmount(), cash.getAmount().negate(), cash.getUserId());
            if (c2 != 1) throw new BussinessException("更新用户账户信息失败");

        }
    }


    @Override
    public void doCashNotifyHR(Map<String, String> retMap) throws Exception {
        // 提现参数校验
        Cash cash = cashMapper.selectOne(new Cash(t -> {
            t.setDelFlag(GenericPo.DELFLAG.NORMAL.code);
            t.setOrderNo(retMap.get("orderNo"));
        }));
        if (null == cash) {
            throw new BussinessException("提现记录不存在");
        }
        if (cash.getStatus() != Cash.STATUS.T3.code) {
            log.error("提现已处理，订单号：" + retMap.get("orderNo"));
            return;
        }

        if (!("0000".equals(retMap.get("respCode")) || "P000".equals(retMap.get("respCode")))) {
            // 代付失败
            int c1 = cashMapper.updateByPrimaryKeySelective(new Cash(t -> {
                t.setId(cash.getId());
                t.setUpdateTime(new Date());
                t.setStatus(Cash.STATUS.T5.code);
                t.setRemark(retMap.get("respDesc"));
                t.setOutStatus(retMap.get("respCode"));
                t.setOutMsg(JSON.toJSONString(retMap));
            }));
            if (c1 != 1) throw new BussinessException("更新提现记录失败");

            //资金记录
            Account account = accountMapper.selectByUID(cash.getUserId());
            int c2 = accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T8, account, "提现解冻，解冻金额：" + cash.getAmount() + "元。"));
            if (c2 != 1) throw new BussinessException("保存资金记录失败");
            //解冻用户资金账户
            int c3 = accountMapper.updateAccount(BigDecimal.ZERO, cash.getAmount(), cash.getAmount().negate(), cash.getUserId());
            if (c3 != 1) throw new BussinessException("更新用户账户信息失败");

        } else if ("0000".equals(retMap.get("respCode"))) {
            // 代付提交成功
            int c1 = cashMapper.updateByPrimaryKeySelective(new Cash(t -> {
                t.setId(cash.getId());
                t.setUpdateTime(new Date());
                t.setStatus(Cash.STATUS.T4.code);
                t.setRemark(retMap.get("respDesc"));
                t.setOutStatus(retMap.get("respCode"));
                t.setOutMsg(JSON.toJSONString(retMap));
            }));
            if (c1 != 1) throw new BussinessException("更新提现记录失败");

            //资金记录
            Account account = accountMapper.selectByUID(cash.getUserId());
            int c2 = accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T9, account, "提现成功，扣除金额：" + cash.getAmount() + "元。"));
            if (c2 != 1) throw new BussinessException("保存资金记录失败");
            //解冻用户资金账户
            int c3 = accountMapper.updateAccount(cash.getAmount().negate(), BigDecimal.ZERO, cash.getAmount().negate(), cash.getUserId());
            if (c3 != 1) throw new BussinessException("更新用户账户信息失败");
        } else {
            // 通知状态为处理中，本地不处理，等待最终状态
        }

    }


    @Override
    public void queryOrderByHR(Cash cash) throws Exception {
        Map<String, String> retMap = HRPayUtils.queryTransStatus("0201", cash.getOrderNo());
        if (retMap != null && retMap.size() > 0) {
            if ("paied".equals(retMap.get("payStatus"))){
                // 支付成功
                int c1 = cashMapper.updateByPrimaryKeySelective(new Cash(t -> {
                    t.setId(cash.getId());
                    t.setUpdateTime(new Date());
                    t.setStatus(Cash.STATUS.T4.code);
                    t.setRemark(retMap.get("respDesc"));
                    t.setOutStatus(retMap.get("respCode"));
                    t.setOutMsg(JSON.toJSONString(retMap));
                }));
                if (c1 != 1) throw new BussinessException("更新提现记录失败");

                //资金记录
                Account account = accountMapper.selectByUID(cash.getUserId());
                int c2 = accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T9, account, "提现成功，扣除金额：" + cash.getAmount() + "元。"));
                if (c2 != 1) throw new BussinessException("保存资金记录失败");
                //解冻用户资金账户
                int c3 = accountMapper.updateAccount(cash.getAmount().negate(), BigDecimal.ZERO, cash.getAmount().negate(), cash.getUserId());
                if (c3 != 1) throw new BussinessException("更新用户账户信息失败");
            }else if ("failed".equals(retMap.get("payStatus"))){
                // 支付失败
                int c1 = cashMapper.updateByPrimaryKeySelective(new Cash(t -> {
                    t.setId(cash.getId());
                    t.setUpdateTime(new Date());
                    t.setStatus(Cash.STATUS.T5.code);
                    t.setRemark(retMap.get("respDesc"));
                    t.setOutStatus(retMap.get("respCode"));
                    t.setOutMsg(JSON.toJSONString(retMap));
                }));
                if (c1 != 1) throw new BussinessException("更新提现记录失败");

                //资金记录
                Account account = accountMapper.selectByUID(cash.getUserId());
                int c2 = accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T8, account, "提现解冻，解冻金额：" + cash.getAmount() + "元。"));
                if (c2 != 1) throw new BussinessException("保存资金记录失败");
                //解冻用户资金账户
                int c3 = accountMapper.updateAccount(BigDecimal.ZERO, cash.getAmount(), cash.getAmount().negate(), cash.getUserId());
                if (c3 != 1) throw new BussinessException("更新用户账户信息失败");
            }else{
                // 处理中，本地不处理
            }
        }
    }


    private DaiFuResp sendDaiFuNotifyByLianLian(Cash cash) throws Exception {
//        SysBank sysBank = SysBankService.SERVICE.getByExtCode(bankCard.getBankCode());
//        if (sysBank == null) {
//            throw new BussinessException("系统银行卡不存在，请联系管理员");
//        }
//        String bankAgentId = sysBank.getLianHangNo();
//
//        if (StringUtils.isBlank(bankAgentId)) {
//            throw new BussinessException("收款人账户银行联行号不存在，请联系管理员");
//        }
        PaymentRequestBean paymentRequestBean = new PaymentRequestBean();
        String orderNo = cash.getOrderNo();
        paymentRequestBean.setNo_order(orderNo);
        paymentRequestBean.setDt_order(DateUtils.dateStr3(new Date()));
        paymentRequestBean.setMoney_order(String.valueOf(cash.getAmount()));
        paymentRequestBean.setCard_no(cash.getBankNo());
        paymentRequestBean.setAcct_name(cash.getRealName());
        paymentRequestBean.setInfo_order("代付");
        paymentRequestBean.setFlag_card("0");
        paymentRequestBean.setMemo("代付");
        // 填写商户自己的接收付款结果回调异步通知
        String webUrl = redisService.get(ConfigNID.WEB_SERVER_URL);
        paymentRequestBean.setNotify_url(webUrl + PartnerConfig.DF_NOTIFY_URL);
        paymentRequestBean.setOid_partner(PartnerConfig.OID_PARTNER);
        paymentRequestBean.setApi_version(PartnerConfig.VERSION);
        paymentRequestBean.setSign_type(PartnerConfig.SIGN_TYPE);
        // 用商户自己的私钥加签
        paymentRequestBean.setSign(SignUtil.genRSASign(JSON.parseObject(JSON.toJSONString(paymentRequestBean))));
        String jsonStr = JSON.toJSONString(paymentRequestBean);
        log.info("实时付款请求报文：" + jsonStr);
        // 用银通公钥对请求参数json字符串加密
        // 报Illegal key
        // size异常时，可参考这个网页解决问题http://www.wxdl.cn/java/security-invalidkey-exception.html
        String encryptStr = LianLianPaySecurity.encrypt(jsonStr, PartnerConfig.YT_PUB_KEY);
        if (StringUtils.isBlank(encryptStr)) {
            // 加密异常
            log.error("加密异常:");
            throw new BussinessException("加密异常");
        }
        com.alibaba.fastjson.JSONObject json = new com.alibaba.fastjson.JSONObject();
        json.put("oid_partner", PartnerConfig.OID_PARTNER);
        json.put("pay_load", encryptStr);
        String response = HttpUtil.post("https://instantpay.lianlianpay.com/paymentapi/payment.htm", json, "UTF-8");
        System.out.println("响应：" + response);
        DaiFuResp daiFuResp = new DaiFuResp();
        if (StringUtils.isBlank(response)) {
            throw new BussinessException("请求数据为空");
        }
        PaymentResponseBean paymentResponseBean = com.alibaba.fastjson.JSONObject.parseObject(response, PaymentResponseBean.class);
        String retCode = paymentResponseBean.getRet_code();
        if ("0000".equals(retCode)) {
            daiFuResp.setStatus(EPayConsts.RES_FLAG_SUCCESS);
        } else if ("4002".equals(paymentResponseBean.getRet_code()) || "4004".equals(paymentResponseBean.getRet_code())) {
            daiFuResp.setStatus(EPayConsts.RES_FLAG_FALSE);
        } else if (RetCodeEnum.isNeedQuery(paymentResponseBean.getRet_code())) {
            // 出现1002，2005，4006，4007，4009，9999这6个返回码时（或者对除了0000之后的code都查询一遍查询接口）调用付款结果查询接口，明确订单状态，不能私自设置订单为失败状态，以免造成这笔订单在连连付款成功了，而商户设置为失败
            // 第一次测试对接时，返回{"ret_code":"4007","ret_msg":"敏感信息解密异常"},可能原因报文加密用的公钥改动了,demo中的公钥是连连公钥，商户生成的公钥用于上传连连商户站用于连连验签，生成的私钥用于加签
            daiFuResp.setStatus(EPayConsts.RES_FLAG_UNKNOWN);
        } else {
            daiFuResp.setStatus(EPayConsts.RES_FLAG_FALSE);
        }
        daiFuResp.setRemark(paymentResponseBean.getRet_msg());
        return daiFuResp;
    }

    @Override
    public void handleOrderByLianLian(PayDataBean payDataBean) throws Exception {
        Cash cash = cashMapper.selectOne(new Cash(c -> {
            c.setOrderNo(payDataBean.getNo_order());
        }));
        if (null == cash) {
            throw new BussinessException("订单为空");
        }
        if (cash.getStatus() == Cash.STATUS.T3.code) {
            if (cash.getAmount().doubleValue() == new BigDecimal(payDataBean.getMoney_order()).doubleValue() && Objects.equals(PayResultEnum.SUCCESS.getCode(), payDataBean.getResult_pay())) {
                Account account = accountMapper.selectByUID(cash.getUserId());
                //资金记录
                accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T9, account, "提现扣除，扣除金额：" + cash.getAmount() + "元。"));
                //更新用户资金账户
                accountMapper.updateAccount(cash.getAmount().negate(), BigDecimal.ZERO, cash.getAmount().negate(), cash.getUserId());
                //处理提现订单
                cash.setActualArrival(new BigDecimal(payDataBean.getMoney_order()));
                cash.setUpdateTime(new Date());
                cash.setOutOrderNo(payDataBean.getOid_paybill());
                cash.setOutMsg(JSON.toJSONString(payDataBean));
                cash.setStatus(Cash.STATUS.T4.code);
                cashMapper.updateByPrimaryKeySelective(cash);
            } else if (payDataBean.getResult_pay().equals(PaymentStatusEnum.PAYMENT_FAILURE.getValue())) {
                //解冻用户资金账户
                Account account = accountMapper.selectByUID(cash.getUserId());
                //资金记录
                accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T8, account, "提现解冻，解冻金额：" + cash.getAmount() + "元。"));

                accountMapper.updateAccount(BigDecimal.ZERO, cash.getAmount(), cash.getAmount().negate(), cash.getUserId());
                //处理提现订单
                cash.setUpdateTime(new Date());
                cash.setStatus(Cash.STATUS.T5.code);
                cash.setOutOrderNo(payDataBean.getOid_paybill());
                cash.setOutMsg(JSON.toJSONString(payDataBean));
                cashMapper.updateByPrimaryKeySelective(cash);
            } else {
                // 退款这种情况是极小概率情况下才会发生的，个别银行处理机制是先扣款后再打款给用户时，
                // 才检验卡号姓名信息的有效性，当卡号姓名信息有误发生退款，实际上钱没打款到商户。
                // 这种情况商户代码上也可不做考虑，如发生用户投诉未收到钱，可直接联系连连客服，连连会跟银行核对
                // 退款情况，异步通知会通知两次，先通知成功，后通知退款（极小概率情况下才会发生的）

                //解冻用户资金账户
                Account account = accountMapper.selectByUID(cash.getUserId());
                //资金记录
                accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T8, account, "提现解冻，解冻金额：" + cash.getAmount() + "元。"));
                accountMapper.updateAccount(BigDecimal.ZERO, cash.getAmount(), cash.getAmount().negate(), cash.getUserId());
                //处理提现订单
                cash.setUpdateTime(new Date());
                cash.setStatus(Cash.STATUS.T5.code);
                cash.setOutOrderNo(payDataBean.getOid_paybill());
                cash.setOutMsg(JSON.toJSONString(payDataBean));
                cashMapper.updateByPrimaryKeySelective(cash);
            }
        }
    }


    @Override
    public void queryOrderByLianLian(Cash cash) throws Exception {
        // 连连内部测试环境数据
        QueryPaymentRequestBean queryRequestBean = new QueryPaymentRequestBean();
        queryRequestBean.setNo_order(cash.getOrderNo());
        queryRequestBean.setOid_partner(PartnerConfig.OID_PARTNER);
        queryRequestBean.setApi_version(PartnerConfig.VERSION);
        queryRequestBean.setSign_type(PartnerConfig.SIGN_TYPE);
        queryRequestBean.setSign(SignUtil.genRSASign(JSON.parseObject(JSON.toJSONString(queryRequestBean))));
        String queryResult = HttpUtil.post("https://instantpay.lianlianpay.com/paymentapi/queryPayment.htm",
                JSON.parseObject(JSON.toJSONString(queryRequestBean)), "UTF-8");
        log.info("实时付款查询接口响应报文：" + queryResult);
        if (StringUtils.isBlank(queryResult)) {
            // 可抛异常，查看原因
            log.error("实时付款查询接口响应异常");
            throw new BussinessException("实时付款查询接口响应异常");
        }
        QueryPaymentResponseBean paymentResponseBean = com.alibaba.fastjson.JSONObject.parseObject(queryResult, QueryPaymentResponseBean.class);

        // 先对结果验签
        boolean signCheck = TraderRSAUtil.checksign(PartnerConfig.YT_PUB_KEY, SignUtil.genSignData(com.alibaba.fastjson.JSONObject.parseObject(queryResult)), paymentResponseBean.getSign());
        if (!signCheck) {
            // 传送数据被篡改，可抛出异常，再人为介入检查原因
            log.error("返回结果验签异常,可能数据被篡改");
            throw new BussinessException("返回结果验签异常,可能数据被篡改");
        }
        String rtnCode = paymentResponseBean.getRet_code();
        String resultPay = paymentResponseBean.getResult_pay();

        if (PaymentStatusEnum.PAYMENT_FAILURE.getValue().equals(resultPay)) {
            cash.setRemark("申请成功,银行返回失败");
        } else if (PaymentStatusEnum.PAYMENT_CLOSED.getValue().equals(resultPay)) {
            cash.setRemark("付款关闭,申请失败");
        } else if (PaymentStatusEnum.PAYMENT_RETURN.getValue().equals(resultPay)) {
            cash.setRemark("付款第一次为success,第二次是CANCEL");
        } else if (PaymentStatusEnum.PAYMENT_DEALING.getValue().equals(resultPay)) {
            cash.setRemark("等待银行回调结果");
        } else if (PaymentStatusEnum.PAYMENT_CHECK.getValue().equals(resultPay)) {
            cash.setRemark("复核申请-疑似重复订");
        }

        if ("0000".equals(rtnCode) && Objects.equals(PayResultEnum.SUCCESS.getCode(), resultPay)) {
            //成功
            Account account = accountMapper.selectByUID(cash.getUserId());
            //资金记录
            accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T9, account, "提现扣除，扣除金额：" + cash.getAmount() + "元。"));
            //更新用户资金账户
            accountMapper.updateAccount(cash.getAmount().negate(), BigDecimal.ZERO, cash.getAmount().negate(), cash.getUserId());
            //处理提现订单
            cash.setActualArrival(new BigDecimal(paymentResponseBean.getMoney_order()));
            cash.setUpdateTime(new Date());
            cash.setOutOrderNo(paymentResponseBean.getOid_paybill());
            cash.setOutMsg(JSON.toJSONString(paymentResponseBean));
            cash.setStatus(Cash.STATUS.T4.code);
            cashMapper.updateByPrimaryKeySelective(cash);

        } else if (RetCodeEnum.isNeedQuery(paymentResponseBean.getRet_code())) {
            //处理中
        } else if ("4002".equals(paymentResponseBean.getRet_code()) || "4004".equals(paymentResponseBean.getRet_code())) {
            //解冻用户资金账户
            Account account = accountMapper.selectByUID(cash.getUserId());
            //资金记录
            accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T8, account, "提现解冻，解冻金额：" + cash.getAmount() + "元。"));

            accountMapper.updateAccount(BigDecimal.ZERO, cash.getAmount(), cash.getAmount().negate(), cash.getUserId());
            //处理提现订单
            cash.setUpdateTime(new Date());
            cash.setStatus(Cash.STATUS.T5.code);
            cash.setOutOrderNo(paymentResponseBean.getOid_paybill());
            cash.setOutMsg(JSON.toJSONString(paymentResponseBean));
            cashMapper.updateByPrimaryKeySelective(cash);
        } else {
            //解冻用户资金账户
            Account account = accountMapper.selectByUID(cash.getUserId());
            //资金记录
            accountLogMapper.insert(AccountLog.buildLog(cash.getUserId(), cash.getAmount(), AccountLog.TYPE.T8, account, "提现解冻，解冻金额：" + cash.getAmount() + "元。"));

            accountMapper.updateAccount(BigDecimal.ZERO, cash.getAmount(), cash.getAmount().negate(), cash.getUserId());
            //处理提现订单
            cash.setUpdateTime(new Date());
            cash.setStatus(Cash.STATUS.T5.code);
            cash.setOutOrderNo(paymentResponseBean.getOid_paybill());
            cash.setOutMsg(JSON.toJSONString(paymentResponseBean));
            cashMapper.updateByPrimaryKeySelective(cash);
        }

    }


}
